#include "VSViewFamily.h"
#include "VSGraphicInclude.h"
#include "VSCubeTexture.h"
using namespace VSEngine2;
VSViewFamily::VSViewFamily(const VSString &ViewFamilyName,VSCamera * pCamera,VSPostEffectSetRPtr pPostEffectSet,bool bDrawDebugInfo,bool bBeforePostDebugDraw )
{
	m_pCamera = pCamera;
	m_pCamera->AddViewFamily(this);
	m_pMaterialSceneRenderder = NULL;
	for(unsigned int i = 0 ; i < RTB_MAX ;i++)
	{
		m_pRenderTargetBuffer[i] = NULL;
	}
	for (unsigned int i = 0 ; i < VSCuller::RG_MAX ; i++)
	{
		m_pDepthStencil[i] = NULL;
	}
	m_uiWidth = 0;
	m_uiHeight = 0;
	m_pPostEffectSet = pPostEffectSet;
	m_bBeforePostDebugDraw = bBeforePostDebugDraw;
	if(bDrawDebugInfo)
	{
		m_pDebugDrawSceneRender = VS_NEW VSDebugDrawSceneRender();
		m_pDebugDrawSceneRender->SetParam(VSRenderer::CF_NONE,VSColorRGBA(0.0f,0.0f,0.0f,1.0f),1.0f,0);
	}
	m_pMaterialSceneRenderder = VS_NEW VSMaterialSceneRender();
	m_pMaterialSceneRenderder->SetParam(VSRenderer::CF_COLOR,VSColorRGBA(1.0f,0.0f,0.0f,1.0f),1.0f,0);
	m_pNormalDepthSceneRender = VS_NEW VSNormalDepthSceneRender();
	m_ViewFamilyName = ViewFamilyName;
	m_bEnable = true;
}
VSViewFamily::~VSViewFamily()
{
	m_pCamera = NULL;
	m_pMaterialSceneRenderder = NULL;
	m_pScene.Clear();
	for(unsigned int i = 0 ; i < RTB_MAX ;i++)
	{
		m_pRenderTargetBuffer[i] = NULL;
	}
	for (unsigned int i = 0 ; i < VSCuller::RG_MAX ; i++)
	{
		m_pDepthStencil[i] = NULL;
	}
	m_pPostEffectSet = NULL;
	m_pDebugDrawSceneRender = NULL;
}
bool VSViewFamily::IsReCreate(unsigned int uiWidth,unsigned int uiHeight)
{
	if (m_uiWidth == uiWidth && m_uiHeight == uiHeight)
	{
		return false;
	}
	return true;
}
VSRenderTarget * VSViewFamily::GetFinalColorRT()
{
	if (m_pPostEffectSet && m_pPostEffectSet->GetResource())
	{
		return m_pPostEffectSet->GetResource()->GetEndTarget(0);
	}
	else
	{
		return m_pRenderTargetBuffer[RTB_COLOR];
	}
}
VSDebugDraw * VSViewFamily::GetDebugDraw(unsigned int uiRenderGroup)
{
	if (m_pDebugDrawSceneRender)
	{
		return m_pDebugDrawSceneRender->GetDebugDraw(uiRenderGroup);
	}
	return NULL;
}
void VSViewFamily::SetUseState(VSRenderState & RenderState,unsigned int uiRenderStateInheritFlag)
{
	m_pMaterialSceneRenderder->SetUseState(RenderState,uiRenderStateInheritFlag);
}
void VSViewFamily::ClearUseState()
{
	m_pMaterialSceneRenderder->ClearUseState();
}

void VSViewFamily::Update(double dAppTime)
{
	VSArray<VSScene *> Temp ;
	if (!m_pCamera)
	{
		return ;
	}
	if (!m_pCamera->m_bEnable)
	{
		return ;
	}
	Temp.Clear();	
	Temp.AddElement(m_pScene,0,m_pScene.GetNum() - 1);
	if (Temp.GetNum() > 0)
	{
		m_Culler.ClearPlaneState();
		m_Culler.ClearAllPlane();
		m_Culler.ClearVisibleSet();
		m_Culler.ClearLight();
		m_Culler.PushCameraPlane(*m_pCamera);
		for (unsigned int i = 0 ; i < Temp.GetNum() ;i++)
		{
			VSScene * pScene = Temp[i];
			if (!pScene)
			{
				continue;
			}

			pScene->ComputeVisibleSet(m_Culler,false,dAppTime);	
	
		}

		if(m_Culler.GetAllVisibleNum() == 0)
			return ;
		m_Culler.Sort();
		for (unsigned int i = 0 ; i < Temp.GetNum() ;i++)
		{
			VSScene * pScene = Temp[i];
			if (!pScene)
			{
				continue;
			}
			for (unsigned int i = 0 ; i < pScene->GetAllLightNum() ; i++)
			{
				VSLight * pLight = pScene->GetAllLight(i);
				if (pLight && pLight->m_bEnable)
				{
					pLight->Cullby(m_Culler);
				}
			}
		}
	}
}
void VSViewFamily::Draw(double dAppTime)
{
	if (m_pCamera && m_Culler.GetAllVisibleNum() > 0)
	{
		if (!m_pCamera->m_bEnable)
		{
			return ;
		}
		m_pNormalDepthSceneRender->Draw(m_Culler,dAppTime);
		m_pMaterialSceneRenderder->Draw(m_Culler,dAppTime);	

		if (m_pDebugDrawSceneRender)
		{
			m_pDebugDrawSceneRender->ClearRTAndDepth();
			if (m_bBeforePostDebugDraw)
			{
				m_pDebugDrawSceneRender->AddRenderTarget(m_pRenderTargetBuffer[RTB_COLOR]);
			}
			else
			{
				m_pDebugDrawSceneRender->AddRenderTarget(GetFinalColorRT());
			}

			for (unsigned int i = 0 ; i < VSCuller::RG_MAX ; i++)
			{
				m_pDebugDrawSceneRender->SetDepthStencil(m_pDepthStencil[i],i);
			}
		}

		if (m_bBeforePostDebugDraw && m_pDebugDrawSceneRender)
		{
			m_pDebugDrawSceneRender->Draw(m_Culler,dAppTime);
		}

		if (m_pPostEffectSet && m_pPostEffectSet->GetResource())
		{	
			m_pPostEffectSet->GetResource()->Draw(m_Culler,dAppTime);

		}
		if (!m_bBeforePostDebugDraw && m_pDebugDrawSceneRender)
		{
			m_pDebugDrawSceneRender->Draw(m_Culler,dAppTime);
		}
	}
}
void VSViewFamily::CreateRenderTargetBuffer(unsigned int uiWidth,unsigned int uiHeight)
{
	m_uiHeight = uiHeight;
	m_uiWidth = uiWidth;
	for(unsigned int i = 0 ; i < RTB_MAX ;i++)
	{
		m_pRenderTargetBuffer[i] = NULL;
	}
	VS2DTexture * pTexture = VS_NEW VS2DTexture(m_uiWidth,m_uiHeight,VSRenderer::SFT_X8R8G8B8);
	VSRenderTarget * pRenderTarget = VSResourceManager::CreateRenderTarget(pTexture,VSRenderer::ms_pRenderer->GetCurMultisample());
	m_pRenderTargetBuffer[RTB_COLOR] = pRenderTarget;

	VS2DTexture * pNormalDepthTexture = VS_NEW VS2DTexture(m_uiWidth,m_uiHeight,VSRenderer::SFT_A16B16G16R16F);
	VSRenderTarget * pNormalDepthRenderTarget = VSResourceManager::CreateRenderTarget(pNormalDepthTexture,VSRenderer::ms_pRenderer->GetCurMultisample());
	m_pRenderTargetBuffer[RTB_NORMALDEPTH] = pNormalDepthRenderTarget;

	for (unsigned int i = 0 ; i < VSCuller::RG_MAX ; i++)
	{
		m_pDepthStencil[i] = NULL;
		m_pDepthStencil[i] = VSResourceManager::CreateDepthStencil(m_uiWidth,m_uiHeight,VSRenderer::ms_pRenderer->GetCurMultisample(),VSRenderer::SFT_D24S8);
	}

	if (m_pPostEffectSet && m_pPostEffectSet->GetResource())
	{
		static VSArray<VSRenderTarget *> Temp;
		Temp.Clear();
		Temp.AddElement(m_pRenderTargetBuffer[RTB_COLOR]);
		m_pPostEffectSet->GetResource()->SetBeginTargetArray(&Temp);
		m_pPostEffectSet->GetResource()->CheckReCreateRT(uiWidth,uiHeight);
	}

	m_pNormalDepthSceneRender->ClearRTAndDepth();
	m_pNormalDepthSceneRender->AddRenderTarget(m_pRenderTargetBuffer[RTB_NORMALDEPTH]);
	for (unsigned int i = 0 ; i < VSCuller::RG_MAX ; i++)
	{
		m_pNormalDepthSceneRender->SetDepthStencil(m_pDepthStencil[i],i);
	}

	m_pMaterialSceneRenderder->ClearRTAndDepth();
	m_pMaterialSceneRenderder->AddRenderTarget(m_pRenderTargetBuffer[RTB_COLOR]);
	for (unsigned int i = 0 ; i < VSCuller::RG_MAX ; i++)
	{
		m_pMaterialSceneRenderder->SetDepthStencil(m_pDepthStencil[i],i);
	}

	if (m_pDebugDrawSceneRender)
	{
		m_pDebugDrawSceneRender->ClearRTAndDepth();
		if (m_bBeforePostDebugDraw)
		{
			m_pDebugDrawSceneRender->AddRenderTarget(m_pRenderTargetBuffer[RTB_COLOR]);
		}
		else
		{
			m_pDebugDrawSceneRender->AddRenderTarget(GetFinalColorRT());
		}
		
		for (unsigned int i = 0 ; i < VSCuller::RG_MAX ; i++)
		{
			m_pDebugDrawSceneRender->SetDepthStencil(m_pDepthStencil[i],i);
		}
	}
	

}
VSWindowViewFamily::VSWindowViewFamily(const VSString &ViewFamilyName,VSCamera * pCamera,VSPostEffectSetRPtr  pPostEffectSet,int iWindowID,bool bDrawDebugInfo ,bool bBeforePostDebugDraw)
					:VSViewFamily(ViewFamilyName,pCamera,pPostEffectSet,bDrawDebugInfo,bBeforePostDebugDraw)
{

	
	m_iWindowID = iWindowID;
	m_pScreenQuadRenderer = VS_NEW VSPEScreenQuadSceneRender();

}
VSWindowViewFamily::~VSWindowViewFamily()
{
	m_pScreenQuadRenderer = NULL;
	
}
void VSWindowViewFamily::Draw(double dAppTime)
{

	unsigned int uiHeight = VSRenderer::ms_pRenderer->GetScreenHeight();
	unsigned int uiWidth = VSRenderer::ms_pRenderer->GetScreenWith();
	VSRenderer::ms_pRenderer->UseWindow(m_iWindowID);
	if (VSRenderer::ms_pRenderer->IsWindowed())
	{

		VSRenderer::ChildWindowInfo * pChildInfo = VSRenderer::ms_pRenderer->GetChildWindowInfo(m_iWindowID);
		if (pChildInfo)
		{
			uiHeight = pChildInfo->m_uiHeight;
			uiWidth = pChildInfo->m_uiWidth;
		}

	}

	if (IsReCreate(uiWidth,uiHeight))
	{
		CreateRenderTargetBuffer(uiWidth,uiHeight);
	}

	VSViewFamily::Draw(dAppTime);
	
	if (m_pScreenQuadRenderer)
	{
		VSRenderTarget *pRenderTarget = GetFinalColorRT();
		VSMAC_ASSERT(pRenderTarget);

		m_pScreenQuadRenderer->SetSourceTarget(pRenderTarget->GetCreateBy());
		m_pScreenQuadRenderer->Draw(m_Culler,dAppTime);
	}
	

}
void VSWindowViewFamily::CreateRenderTargetBuffer(unsigned int uiWidth,unsigned int uiHeight)
{
	VSViewFamily::CreateRenderTargetBuffer(uiWidth,uiHeight);
	if(m_pScreenQuadRenderer && m_pScreenQuadRenderer->IsReCreate(uiWidth,uiHeight))
	{
		m_pScreenQuadRenderer->CreateRT(uiWidth,uiHeight);
	}
}
VSCaptureViewFamily::VSCaptureViewFamily(const VSString &ViewFamilyName,unsigned int uiWidth,unsigned int uiHeight,VSCamera * pCamera,VSPostEffectSetRPtr  pPostEffectSet,bool bDrawDebugInfo,bool bBeforePostDebugDraw)
:VSViewFamily(ViewFamilyName,pCamera,pPostEffectSet,bDrawDebugInfo,bBeforePostDebugDraw)
{
	VSMAC_ASSERT(uiWidth && uiHeight);
	if (IsReCreate(uiWidth,uiHeight))
	{
		CreateRenderTargetBuffer(uiWidth,uiHeight);
	}
}
VSCaptureViewFamily::~VSCaptureViewFamily()
{

}
void VSCaptureViewFamily::Draw(double dAppTime)
{
	VSViewFamily::Draw(dAppTime);
	
}
void VSCaptureViewFamily::SetSize(unsigned int uiWidth,unsigned int uiHeight)
{
	if (IsReCreate(uiWidth,uiHeight))
	{
		CreateRenderTargetBuffer(uiWidth,uiHeight);
	}
}

VS3DCaptureViewFamily::VS3DCaptureViewFamily(const VSString &ViewFamilyName,unsigned int uiWidth,unsigned int uiHeight,VSCamera * pCamera,VSPostEffectSetRPtr  pPostEffectSet,bool bDrawDebugInfo,bool bBeforePostDebugDraw)
:VSCaptureViewFamily(ViewFamilyName,uiWidth,uiHeight,pCamera,pPostEffectSet,bDrawDebugInfo,bBeforePostDebugDraw)
{
	VSMAC_ASSERT(uiWidth && uiHeight);
	if (IsReCreate(uiWidth,uiHeight))
	{
		CreateRenderTargetBuffer(uiWidth,uiHeight);
	}
}
VS3DCaptureViewFamily::~VS3DCaptureViewFamily()
{

}
void VS3DCaptureViewFamily::SetSize(unsigned int uiWidth,unsigned int uiHeight)
{
	if (IsReCreate(uiWidth,uiHeight))
	{
		CreateRenderTargetBuffer(uiWidth,uiHeight);
	}
}
void VS3DCaptureViewFamily::Draw(double dAppTime)
{
	if (m_pCamera && m_Culler.GetAllVisibleNum() > 0)
	{
		if (!m_pCamera->m_bEnable)
		{
			return ;
		}
		
		for (unsigned int k = 0 ; k < VSCubeTexture::F_MAX ;k++)
		{
			if (m_pPostEffectSet && m_pPostEffectSet->GetResource())
			{
				static VSArray<VSRenderTarget *> Temp;
				Temp.Clear();
				Temp.AddElement(m_pRenderTargetBuffer[k]);
				m_pPostEffectSet->GetResource()->SetBeginTargetArray(&Temp);
				m_pPostEffectSet->GetResource()->CheckReCreateRT(m_uiWidth,m_uiHeight);
			}

			m_pMaterialSceneRenderder->ClearRTAndDepth();
			m_pMaterialSceneRenderder->AddRenderTarget(m_pRenderTargetBuffer[k]);
			for (unsigned int i = 0 ; i < VSCuller::RG_MAX ; i++)
			{
				m_pMaterialSceneRenderder->SetDepthStencil(m_pDepthStencil[i],i);
			}

			if (m_pDebugDrawSceneRender)
			{
				m_pDebugDrawSceneRender->ClearRTAndDepth();
				if (m_bBeforePostDebugDraw)
				{
					m_pDebugDrawSceneRender->AddRenderTarget(m_pRenderTargetBuffer[k]);
				}
				else
				{
					m_pDebugDrawSceneRender->AddRenderTarget(GetFinalColorRT());
				}

				for (unsigned int i = 0 ; i < VSCuller::RG_MAX ; i++)
				{
					m_pDebugDrawSceneRender->SetDepthStencil(m_pDepthStencil[i],i);
				}
			}
			m_pNormalDepthSceneRender->Draw(m_Culler,dAppTime);

			if (m_bBeforePostDebugDraw && m_pDebugDrawSceneRender)
			{
				m_pDebugDrawSceneRender->Draw(m_Culler,dAppTime);
			}

			if (m_pPostEffectSet && m_pPostEffectSet->GetResource())
			{	
				m_pPostEffectSet->GetResource()->Draw(m_Culler,dAppTime);

			}
			if (!m_bBeforePostDebugDraw && m_pDebugDrawSceneRender)
			{
				m_pDebugDrawSceneRender->Draw(m_Culler,dAppTime);
			}
		}
	}
}
void VS3DCaptureViewFamily::CreateRenderTargetBuffer(unsigned int uiWidth,unsigned int uiHeight)
{
	m_uiHeight = uiHeight;
	m_uiWidth = uiWidth;
	for(unsigned int i = 0 ; i < RTB_MAX ;i++)
	{
		m_pRenderTargetBuffer[i] = NULL;
	}
	VSCubeTexture * pTexture = VS_NEW VSCubeTexture(m_uiWidth,m_uiHeight,VSRenderer::SFT_X8R8G8B8);
	for (unsigned int i = 0 ; i < VSCubeTexture::F_MAX ;i++)
	{
		VSRenderTarget * pRenderTarget = VSResourceManager::CreateRenderTarget(pTexture,VSRenderer::ms_pRenderer->GetCurMultisample(),0,i);
		m_pRenderTargetBuffer[i] = pRenderTarget;
	}
	

	for (unsigned int i = 0 ; i < VSCuller::RG_MAX ; i++)
	{
		m_pDepthStencil[i] = NULL;
		m_pDepthStencil[i] = VSResourceManager::CreateDepthStencil(m_uiWidth,m_uiHeight,VSRenderer::ms_pRenderer->GetCurMultisample(),VSRenderer::SFT_D24S8);
	}

	


}